{
 "cells": [
  {
   "cell_type": "markdown",
   "source": [
    "# MetaClass元类\n",
    "MetaClass元类，本质也是一个类，但和普通类的用法不同，它可以对类内部的定义（包括类属性和类方法）进行动态的修改。"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% md\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "如果想把一个类设计成 MetaClass 元类，其必须符合以下条件：\n",
    "1.必须显式继承自 type 类；\n",
    "2.类中需要定义并实现 __new__() 方法，该方法一定要返回该类的一个实例对象，因为在使用元类创建类时，该 __new__() 方法会自动被执行，用来修改新建的类。"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% md\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "outputs": [],
   "source": [
    "# 定义一个元类\n",
    "class FirstMetaClass(type):\n",
    "    # cls代表动态修改的类\n",
    "    # name代表动态修改的类名\n",
    "    # bases代表动态修改的类的所有父类\n",
    "    # attrs代表动态修改的类的所有的属性、方法组成的字典\n",
    "    def __new__(cls, name, bases, attrs):\n",
    "        print(\"name: \", name)\n",
    "        print(\"bases: \", bases)\n",
    "        print(\"attrs: \", attrs)\n",
    "        attrs['name'] = 'python study'\n",
    "        attrs['say'] = lambda self: print('调用say()实例方法')\n",
    "        return super().__new__(cls, name, bases, attrs)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "在这个元类的 __new__() 方法中，手动添加了一个 name 属性和 say() 方法。这意味着，通过 FirstMetaClass 元类创建的类，会额外添加 name 属性和 say() 方法。"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% md\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "name:  ClassMates\n",
      "bases:  (<class 'object'>,)\n",
      "attrs:  {'__module__': '__main__', '__qualname__': 'ClassMates', 'age': 28}\n",
      "python study\n",
      "调用say()实例方法\n"
     ]
    }
   ],
   "source": [
    "# 定义类时， 指定元类\n",
    "class ClassMates(object, metaclass=FirstMetaClass):\n",
    "    age = 28\n",
    "    pass\n",
    "\n",
    "cm = ClassMates()\n",
    "print(cm.name)\n",
    "cm.say()"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}